package com.example.myapplication

import android.content.Context
import android.opengl.*
import android.util.Log
import com.example.total.R
import com.threed.jpct.*
import com.threed.jpct.Matrix
import com.threed.jpct.util.BitmapHelper
import com.threed.jpct.util.MemoryHelper
import java.io.IOException
import java.io.InputStream
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

class MyRender(private var context: Context) : GLSurfaceView.Renderer {

    private var time = System.nanoTime() // 更新帧率的计时器
    private var fb: FrameBuffer? = null // 帧缓冲
    private var sun: Light? = null // 默认光源
    private var cube: Object3D? = null // 立方体3D模型
    private var world: World? = null // 3D世界
    private var fps = 0 // 每秒帧数
    private var Model: Object3D? = null // 普通3DS模型
    private var Model1: Object3D? = null // 普通3DS模型
    private var Model2: Object3D? = null // 普通3DS模型
    private var touchTurn = 0f // 触摸处理旋转角度Y
    private var touchTurnUp = 0f // 触摸处理旋转角度X

    // 行走动画变量
    private var an = 2
    private var ind = 0f

    override fun onSurfaceChanged(gl: GL10, w: Int, h: Int) {
        if (fb != null) {
            fb!!.dispose()
        }
        fb = FrameBuffer(gl, w, h) // 创建FrameBuffer对象，并设置其大小
        GLES20.glViewport(0, 0, w, h) // 设置视口大小，这里是整个屏幕
    }

    override fun onSurfaceCreated(gl: GL10, config: EGLConfig) {
        gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f) // 设置背景颜色为黑色

        world = World() // 创建一个3D世界
        world!!.setAmbientLight(150, 150, 150) // 设置环境光照强度(红色、绿色、蓝色分别为150)
        // 加载三张纹理并添加到TextureManager中
        val textu1=MyQueryHelper.list[6]
        var resourceId = context.resources.getIdentifier("drawable/$textu1", null, context.packageName)
        var drawable = context.resources.getDrawable(resourceId)
        var bitmap = BitmapHelper.convert(drawable)
        var scaledBitmap = BitmapHelper.rescale(bitmap, 64, 64)
        var texture = Texture(scaledBitmap)//纹理
        val textu2=MyQueryHelper.list[7]
             resourceId = context.resources.getIdentifier("drawable/$textu2", null, context.packageName)
             drawable = context.resources.getDrawable(resourceId)
             bitmap = BitmapHelper.convert(drawable)
             scaledBitmap = BitmapHelper.rescale(bitmap, 64, 64)
        var  texture1 = Texture(scaledBitmap)//纹理
        val  textu3=MyQueryHelper.list[8]
             resourceId = context.resources.getIdentifier("drawable/$textu3", null, context.packageName)
             drawable = context.resources.getDrawable(resourceId)
             bitmap = BitmapHelper.convert(drawable)
             scaledBitmap = BitmapHelper.rescale(bitmap, 64, 64)
        var  texture2 = Texture(scaledBitmap)//纹理
        TextureManager.getInstance().addTexture("texture", texture)//赋值
        TextureManager.getInstance().addTexture("texture1", texture1)
        TextureManager.getInstance().addTexture("texture2", texture2)

        cube = Primitives.getCube(10F) // 创建一个10F大小的立方体用于相机校准
        cube!!.calcTextureWrapSpherical() // 为其计算纹理坐标，使其表面贴上纹理
        cube!!.setTexture("texture") // 设置纹理为"texture"
        cube!!.strip() // 将其所有子对象中相同材质的地块（TriangleGroup）合并到同一Object3D中
        cube!!.build() // 计算所有VertexController（如平滑，光照计算等）

        Model = loadModel(MyQueryHelper.list[6]+".3ds", 1f) // 加载"*.3ds"普通3DS模型
        Model!!.setTexture("texture") // 给这个3D模型添加纹理
        Model!!.strip()
        Model!!.build()

        Model1 = loadModel(MyQueryHelper.list[7]+".3ds", 1f) // 加载"*.3ds"普通3DS模型
        Model1!!.setTexture("texture1") // 给这个3D模型添加纹理
        Model1!!.strip()
        Model1!!.build()

        Model2 = loadModel(MyQueryHelper.list[8]+".3ds", 1f) // 加载"*.3ds"普通3DS模型
        Model2!!.setTexture("texture2") // 设定模型纹理
        Model2!!.strip()
        Model2!!.build()

//        mdModel!!.translate(-2f, 0f, 0f) // 平移模型位置

        world!!.addObject(Model) // 将Rock3DS模型添加到世界中
        world!!.addObject(Model1) // 将ChongLou3DS模型添加到世界中
        world!!.addObject(Model2) // 将MD2模型添加到世界中

        sun = Light(world)
        sun!!.setIntensity(250F, 250F, 250F) // 设置光源强度

        val cam = world!!.camera
        cam.moveCamera(Camera.CAMERA_MOVEOUT, 20f) // 移动相机

        cam.lookAt(cube!!.transformedCenter) // 相机观察模型的中心点

        val sv = SimpleVector()
        sv.set(cube!!.transformedCenter)
        sv.y -= 100f
        sv.z -= 100;
        sun!!.setPosition(sv); // 设置光源位置
        MemoryHelper.compact();
    }

    override fun onDrawFrame(gl: GL10) {
        // 清除屏幕颜色和深度缓存
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT or GL10.GL_DEPTH_BUFFER_BIT)

        doAnim() // 进行动画播放和变换

        fb?.clear(RGBColor.BLACK) // 清除帧缓冲的颜色缓存
        world?.renderScene(fb!!) // 将场景渲染到帧缓冲中
        world?.draw(fb!!) // 在OpenGL ES视图中显示帧缓冲
        fb?.display() // 显示帧缓冲内容

        if (touchTurn != 0f) { // 如果用户进行了旋转操作
            Model?.rotateY(touchTurn) // 对Rock3DS模型进行水平方向上的旋转
            Model1?.rotateY(touchTurn) // 对ChongLou3DS模型进行水平方向上的旋转
//            mdModel?.rotateY(touchTurn) // 对MD2模型进行水平方向上的旋转
            touchTurn = 0f
        }

        if (touchTurnUp != 0f) { // 如果用户进行了仰俯角度的旋转操作
            Model?.rotateX(touchTurnUp) // 对Rock3DS模型进行上下方向上的旋转
            Model1?.rotateX(touchTurnUp) // 对ChongLou3DS模型进行上下方向上的旋转
//            mdModel?.rotateX(touchTurnUp) // 对MD2模型进行上下方向上的旋转
            touchTurnUp = 0f
        }

        if (System.nanoTime() - time >= 1000000000) {
            Logger.log("$fps fps")
            Log.d("FPSCounter", "fps: $fps") // 计算并输出帧率
            fps = 0
            time = System.nanoTime()
        }
        fps++
    }
    companion object {
        /**
         * 加载shader代码
         * @param type shader类型: GLES20.GL_VERTEX_SHADER 或 GLES20.GL_FRAGMENT_SHADER
         * @param shaderCode Shader代码
         * @return Shader句柄
         */
        @JvmStatic
        fun loadShader(type: Int, shaderCode: String): Int {
            // 创建一个shader句柄（GLES20.glCreateShader）
            val shader = GLES20.glCreateShader(type)
            // 将shader源码添加到shader并编译它（GLES20.glShaderSource, GLES20.glCompileShader）
            GLES20.glShaderSource(shader, shaderCode)
            GLES20.glCompileShader(shader)
            return shader
        }
    }

    /**
     * 从给定文件名加载3DS模型并返回Object3D对象
     * @param filename 文件名
     * @param scale 模型缩放比例
     * @return 加载的3DS模型的Object3D对象实例
     */
    fun loadModel(filename: String, scale: Float): Object3D {
        var isStream: InputStream? = null
        try {
            // 打开文件的输入流（context.assets?.open）
            isStream = context.assets?.open(filename)
        } catch (e: IOException) {
            e.printStackTrace()
        }
        // 加载3DS模型（Loader.load3DS）
        val model = Loader.load3DS(isStream, scale)
        // 将每个对象进行旋转、平移等变换后合并成一个Object3D对象
        var temp: Object3D?
        var o3d = Object3D(0)
        for (i in model.indices) {
            temp = model[i]
            temp.setCenter(SimpleVector.ORIGIN)
            temp.rotateX((-0.5 * Math.PI).toFloat())
            temp.rotateMesh()
            temp.rotationMatrix = Matrix()
            o3d = Object3D.mergeObjects(o3d, temp)
            o3d.build()
        }
        return o3d
    }

    /**
     * 从给定文件名加载MD2模型并返回Object3D对象实例
     * @param filename 文件名
     * @param scale 模型缩放比例
     * @return 加载的MD2模型的Object3D对象实例，可能为空
     */
    fun loadMdModel(filename: String, scale: Float): Object3D? {
        var isStream: InputStream? = null
        try {
            // 打开文件的输入流（context.assets?.open）
            isStream = context.assets?.open(filename)
        } catch (e: IOException) {
            e.printStackTrace()
        }
        // 加载MD2模型（Loader.loadMD2）
        return Loader.loadMD2(isStream, scale)
    }

    /**
     * 更新一帧中的动画状态
     */
    fun doAnim() {
        // 计算当前帧数（ind）并调用animate()函数更新动画状态（mdModel?.animate）
        ind += 0.018f
        if (ind > 1f) {
            ind -= 1f
        }
        Model2?.animate(ind, an)
    }

    /**
     * 设置触摸屏幕时相应的水平旋转角度
     * @param count 角度值
     */
    fun setTouchTurn(count: Float) {
        touchTurn = count
    }

    /**
     * 设置触摸屏幕时相应的垂直旋转角度
     * @param count 角度值
     */
    fun setTouchTurnUp(count: Float) {
        touchTurnUp = count
    }}
